{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:40.289851Z",
     "start_time": "2025-02-27T07:01:37.000935Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 2.0.2\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.6.0+cu126\n",
      "cuda:0\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:42.396694Z",
     "start_time": "2025-02-27T07:01:40.290864Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import random_split\n",
    "\n",
    "# fashion_mnist图像分类数据集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
    "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))"
   ],
   "outputs": [],
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:42.402693Z",
     "start_time": "2025-02-27T07:01:42.396694Z"
    }
   },
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "# print(cal_mean_std(train_ds))\n",
    "# 0.2860， 0.3205\n",
    "transforms = nn.Sequential(\n",
    "    Normalize([0.2856], [0.3202])\n",
    ") # 对每个通道进行标准化"
   ],
   "outputs": [],
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:42.407141Z",
     "start_time": "2025-02-27T07:01:42.402693Z"
    }
   },
   "source": [
    "from torch.utils.data.dataloader import DataLoader\n",
    "\n",
    "batch_size = 32\n",
    "# 从数据集到dataloader\n",
    "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=4)\n",
    "test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ],
   "outputs": [],
   "execution_count": 4
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:42.419037Z",
     "start_time": "2025-02-27T07:01:42.407141Z"
    }
   },
   "source": [
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.pool = nn.MaxPool2d(2, 2)\n",
    "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10)\n",
    "        \n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x)))))\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x)))))\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x)))))\n",
    "        x = self.flatten(x)\n",
    "        x = act(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "    \n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\")\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.weight\tparamerters num: 9216\n",
      "conv2.bias\tparamerters num: 32\n",
      "conv3.weight\tparamerters num: 18432\n",
      "conv3.bias\tparamerters num: 64\n",
      "conv4.weight\tparamerters num: 36864\n",
      "conv4.bias\tparamerters num: 64\n",
      "conv5.weight\tparamerters num: 73728\n",
      "conv5.bias\tparamerters num: 128\n",
      "conv6.weight\tparamerters num: 147456\n",
      "conv6.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 5
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:42.427701Z",
     "start_time": "2025-02-27T07:01:42.419037Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def count_parameters(model): #计算模型总参数量\n",
    "    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "count_parameters(CNN())"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "435306"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 6
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:42.480801Z",
     "start_time": "2025-02-27T07:01:42.427701Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 7
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:45.436132Z",
     "start_time": "2025-02-27T07:01:42.480801Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 8
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:45.442133Z",
     "start_time": "2025-02-27T07:01:45.436132Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 9
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:01:45.463155Z",
     "start_time": "2025-02-27T07:01:45.443063Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 10
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:09:20.428709Z",
     "start_time": "2025-02-27T07:01:45.463155Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                    \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "activation = \"selu\"\n",
    "model = CNN(activation)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/cnn-{activation}\")\n",
    "tensorboard_callback.draw_model(model, [1, 1, 28, 28])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/cnn-{activation}\", save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=1000\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/34380 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "45c70dffe82e4439a9b1cc4a6edafc75"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 13 / global_step 24000\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:09:20.572743Z",
     "start_time": "2025-02-27T07:09:20.429704Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=500)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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q9WK9957T51NE7LDkbNosvMYNWqUuk12LB988AHi4uLQuXNnPP744+ps3LRp02A2M/FKRESecb9E5B0/qUQV0L17dwwfPlztRC6//HK8++67OHXqlNf7r1+/Hjt37kRCQgLi4+PVJmfU8vLysGvXLrfnlZ2JTs60ZWVlqfICIiIib7hfIvKOGR2iCoiIiMDs2bOxdOlSzJo1C6+99hr+/e9/Y8WKFR7vLzuF3r1743//+1+p70ndMxERUWVwv0TkHQMdogqSVP/AgQPVNmXKFFUq8P3336s0f3Fxsdt9e/XqhenTpyM5OVlN5izrDFtubq4qMxDLly9XZ9lSU1Or/P0QEVHNxv0SkWcsXSOqADlD9tRTT2HVqlVqkud3332H9PR0dOzYES1atFATObdt24bjx4+rCZ9XX301kpKSVEcbmfS5Z88eVQN955134uDBg47nlU42N9xwAzZv3owZM2bg0UcfxaRJk1gHTUREZeJ+icg7ZnSIKkDOfi1cuBAvv/yy6mQjZ81eeOEFjB07Fn369FE7C7mU0oD58+dj6NCh6v7//Oc/1URR6YbTpEkTVU/teiZNrrdt2xZDhgxRE0elg85jjz0W1PdKREShj/slIu9MNpvNVsb3iaiKyXoFp0+fxg8//BDsl0JERMT9EoUN5h+JiIiIiCjsMNAhIiIiIqKww9I1IiIiIiIKO8zoEBERERFR2GGgQ0REREREYYeBDhERERERhR0GOkREREREFHYY6BARERERUdhhoENERERERGGHgQ4REREREYUdBjpERERERBR2GOgQERERERHCzf8DokHM388a1v4AAAAASUVORK5CYII="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 12
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:09:25.947620Z",
     "start_time": "2025-02-27T07:09:20.573740Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/cnn-{activation}/best.ckpt\", map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.2574\n",
      "accuracy: 0.9113\n"
     ]
    }
   ],
   "execution_count": 13
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
